<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>拓展内建类</title>
</head>
<body>
<script>

  /*
  * JS中的很多内建类我们都可以沿用功能 比如我现在的需求是需要一个类似数组的功能 也就是要用到数组上的API
  * 但是还要添加很多其他的方法这个时候我们就可以让当前类继承Array
  *
  * 但是继承的时候要注意,如果是非内建类 我们可以在子类的构造函数中super父类的构造(如果子类有额外的对象属性要赋值的话)
  * 但是内建类不行 内建类的属性都是用C语言写的本地实现,我们无法获得也就是说Array内部的数组属性不是定义在构造函数中的
  * 这里也不用担心会存在共享数组的问题，首先这是内建类,另一方面Array内部的东西我们无法访问
  *
  * 只在构造器中定义了一个length属性，而且还是访问器属性 我们如果在子类中写构造函数的话那么会调用父类的构造函数，父类构造
  * 函数内部没有数组属性,所以我们就无法将参数传给父类的数组进行赋值
  *
  * 最好的做法就是不要写构造函数 这个时候父类中数组属性的赋值就会使用本地方法
  *
  *
  *
  * */
  class MyArray extends Array{
    // constructor() {
    //   super();
    // }
    //

    print(){
      console.log("MyArray");
    }

  }

  let myArray = new MyArray([2,1,5,4]);
  console.log(myArray);
  /*
  * map 是一个纯函数,会返回一个新的对象 这个新的对象的创建的底层是调用 new this.constructor[Symbol.species]
  * 实现的 只不过Array中的 static get [Symbol.species] 函数返回的是this.constructor
  *
  * */
  let map = myArray.map(ele => ele*2);
  console.log(map);
  map.print()


  /*
  * 内建类是没有静态方法继承的
  * 之前我们说的继承有干了两件事，第一件是将子类对象.prototype.__proto__ = 父类对象.__proto__
  * 然后将子类对象.__proto__ = 父类对象
  * 所以子类对象可以继承到父类对象的静态方法
  *
  * 但是在内建类不行 比如Array继承了Object(
  *
  *
  * */


  /*
  * 无法继承到父类的静态方法 即无法使用 MyObj.defineProperty()
  * */
  class MyObj extends Object{

  }

  /*
  * 这样的话子类就可以继承到父类的静态方法了
  *
  * 记住对象实现继承的本质是内部的[[prototype]]隐藏属性(__proto__)
  * 你可以在创建对象修改对象构造方法的prototype来实现继承，这是在创建对象之前
  * 一单创建对象之后如果想动态的调整继承的话可以修改对象的__proto__
  *
  * */
  MyObj.__proto__ = Object

  console.log(MyObj);
  console.log(MyObj.assign);


</script>
</body>
</html>